/**
 * 
 */
package metier;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import controller.MatriceDocMot;

/**
 * @author lea, jonathan
 * 
 */
public class Filtre {
	/*
	 * TODO
	 */
	// Renvoit le texte en enlevant les mots les plus fréquents
	public static List<String> trouverPlusFrequent(List<String> texte,String nomFichier) {
		// Comptage des fréquences des mots
		Map<String, Integer> comptageFrequence = MatriceDocMot
				.fabriquerMatriceDocMotFichier(texte);
		if (comptageFrequence != null) {
			Integer nombreDeMot = comptageFrequence.size();
			// Synthèse des fréquences des nombres de mots
			Map<Integer, Set<String>> mapNombreMot = new TreeMap<Integer, Set<String>>();
			// Parcours de tous les mots du texte
			for (Entry<String, Integer> entry : comptageFrequence.entrySet()) {
				String cle = entry.getKey();
				Integer valeur = entry.getValue();
				// Récupération du mot dans la nouvelle MAP grâce à la fréquence
				// du mot
				Set<String> listeMot = mapNombreMot.get(valeur);
				// Si aucun mot n'est correspondant dans la fréquence
				if (listeMot == null) {
					// On initialise la liste de mot
					listeMot = new HashSet<String>();
				}
				// On ajout le mot à la fréquence
				listeMot.add(cle);
				// On met à jour la nouvelle map
				mapNombreMot.put(valeur, listeMot);
			}
			// Prendre la médiane
			mapNombreMot = retournerMedianeHaute(mapNombreMot);
			// Si > à 50% des mots : tenter la médiane de la médiane (en boucle)
			while (sommeDesListeApresMediane(mapNombreMot) > nombreDeMot / 2
					&& mapNombreMot.size() != 1) {
				// Prendre la médiane
				mapNombreMot = retournerMedianeHaute(mapNombreMot);
			}
			// Retour des fréquents
			List<String> motsFrequents = extraireMotsFrequents(mapNombreMot);
			EcrireFichier.ecrireFichier("filtres/plusFrequent/"+nomFichier+".txt", motsFrequents);
			return motsFrequents;
		} else {
			return null;
		}
	}

	/**
	 * Cette fonction retourne les mots les plus fréquents en utilisant la
	 * médiane. Cette méthode est à utilisée après avoir nettoyer le texte.
	 * 
	 * @param texte
	 *            Le texte contenant les fréquents
	 * @return La liste des fréquents
	 */
	public static List<String> trouverMoinsFrequent(List<String> texte,String nomFichier) {
		// Comptage des fréquences des mots
		Map<String, Integer> comptageFrequence = MatriceDocMot
				.fabriquerMatriceDocMotFichier(texte);
		if (comptageFrequence != null) {
			Integer nombreDeMot = comptageFrequence.size();
			// Synthèse des fréquences des nombres de mots
			Map<Integer, Set<String>> mapNombreMot = new TreeMap<Integer, Set<String>>();
			// Parcours de tous les mots du texte
			for (Entry<String, Integer> entry : comptageFrequence.entrySet()) {
				String cle = entry.getKey();
				Integer valeur = entry.getValue();
				// Récupération du mot dans la nouvelle MAP grâce à la fréquence
				// du mot
				Set<String> listeMot = mapNombreMot.get(valeur);
				// Si aucun mot n'est correspondant dans la fréquence
				if (listeMot == null) {
					// On initialise la liste de mot
					listeMot = new HashSet<String>();
				}
				// On ajout le mot à la fréquence
				listeMot.add(cle);
				// On met à jour la nouvelle map
				mapNombreMot.put(valeur, listeMot);
			}
			// Prendre la médiane
			mapNombreMot = retournerMedianeBasse(mapNombreMot);
			// Si > à 50% des mots : tenter la médiane de la médiane (en boucle)
			while (sommeDesListeApresMediane(mapNombreMot) > nombreDeMot / 2
					&& mapNombreMot.size() != 1) {
				// Prendre la médiane
				mapNombreMot = retournerMedianeBasse(mapNombreMot);
			}
			// Retour des fréquents
			List<String> motsFrequents = extraireMotsFrequents(mapNombreMot);
			EcrireFichier.ecrireFichier("filtres/moinsFrequent/"+nomFichier+".txt", motsFrequents);
			return motsFrequents;
		} else {
			return null;
		}
	}

	private static List<String> extraireMotsFrequents(
			Map<Integer, Set<String>> mapNombreMot) {
		List<String> listeRetour = new ArrayList<String>();
		for (Entry<Integer, Set<String>> parcours : mapNombreMot.entrySet()) {
			listeRetour.addAll(parcours.getValue());
		}
		return listeRetour;
	}

	private static int sommeDesListeApresMediane(
			Map<Integer, Set<String>> mapNombreMot) {
		Integer sommeDeMot = 0;
		for (Entry<Integer, Set<String>> parcours : mapNombreMot.entrySet()) {
			sommeDeMot += parcours.getValue().size();
		}
		return sommeDeMot;
	}

	private static Map<Integer, Set<String>> retournerMedianeBasse(
			Map<Integer, Set<String>> mapNombreMot) {
		SortedMap<Integer, Set<String>> mapPreRetour = new TreeMap<>(
				mapNombreMot);
		Map<Integer, Set<String>> mapRetour;
		if (mapNombreMot != null) {
			Integer tailleSortedMap = mapPreRetour.size();
			if (tailleSortedMap == 1) {
				return mapNombreMot;
			} else {
				Integer debutInclus = mapPreRetour.firstKey();
				Integer finExclus = (Integer) mapPreRetour.keySet().toArray()[tailleSortedMap / 2];
				if (debutInclus == finExclus) {
					++finExclus;
				}
				mapRetour = new TreeMap<>(mapPreRetour.subMap(debutInclus,
						finExclus));
			}
			return mapRetour;
		} else {
			return null;
		}
	}

	private static Map<Integer, Set<String>> retournerMedianeHaute(
			Map<Integer, Set<String>> mapNombreMot) {
		SortedMap<Integer, Set<String>> mapPreRetour = new TreeMap<>(
				mapNombreMot);
		Map<Integer, Set<String>> mapRetour;
		if (mapNombreMot != null) {
			Integer tailleSortedMap = mapPreRetour.size();
			if (tailleSortedMap == 1) {
				return mapNombreMot;
			} else {
				Integer debutInclus = (Integer) mapPreRetour.keySet().toArray()[tailleSortedMap / 2];
				mapRetour = new TreeMap<>(mapPreRetour.tailMap(debutInclus));
			}
			return mapRetour;
		} else {
			return null;
		}
	}

	/**
	 * Transforme une String en List de String. Le string est découpé avec les
	 * espaces.
	 * 
	 * @param contenuFichier
	 *            Le String à découper
	 * @return Le string découpé.
	 */
	private static List<String> transformationEnList(String contenuFichier) {
		String[] stringApresSplit = contenuFichier.trim().split(" ");
		List<String> liste = new ArrayList<String>();
		for (int index = 0; index < stringApresSplit.length; index++) {
			liste.add(stringApresSplit[index]);
		}
		return liste;

	}
	
	public static void main(String... args) throws IOException {
		FiltreMetier monFiltre = new FiltreMetier();
		List<String> compilationText =transformationEnList(ChargerFichier.lireFichier("fichiersOriginaux/testTennis/testTennis0.txt"));
		compilationText.addAll(transformationEnList(ChargerFichier.lireFichier("fichiersOriginaux/testTennis/testTennis1.txt")));
		compilationText.addAll(transformationEnList(ChargerFichier.lireFichier("fichiersOriginaux/testTennis/testTennis2.txt")));
		compilationText.addAll(transformationEnList(ChargerFichier.lireFichier("fichiersOriginaux/testTennis/testTennis3.txt")));
		compilationText.addAll(transformationEnList(ChargerFichier.lireFichier("fichiersOriginaux/testTennis/testTennis4.txt")));
		compilationText.addAll(transformationEnList(ChargerFichier.lireFichier("fichiersOriginaux/testTennis/testTennis5.txt")));
		compilationText.addAll(transformationEnList(ChargerFichier.lireFichier("fichiersOriginaux/testTennis/testTennis6.txt")));
		compilationText.addAll(transformationEnList(ChargerFichier.lireFichier("fichiersOriginaux/testTennis/testTennis7.txt")));
		compilationText.addAll(transformationEnList(ChargerFichier.lireFichier("fichiersOriginaux/testTennis/testTennis8.txt")));
		compilationText.addAll(transformationEnList(ChargerFichier.lireFichier("fichiersOriginaux/testTennis/testTennis9.txt")));
		compilationText = monFiltre.accent(compilationText);
		compilationText = monFiltre.minuscule(compilationText);
		compilationText = monFiltre.normalisation(compilationText);
		compilationText = monFiltre.adjectifPossessif(compilationText);
		compilationText = monFiltre.motTailleN(compilationText,3);
		//compilationText = monFiltre.lemmatisation(compilationText);
		trouverPlusFrequent(compilationText,"corpusTennis");
		trouverMoinsFrequent(compilationText,"corpusTennis");
	}
}
